﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AnguaRPGEngine.Library.Parts;
using AnguaRPGEngine.Library.Interfaces;
using AnguaRPGEngine.Library.Systems;
using AnguaRPGEngine.Library.Events;
using AnguaRPGEngine.Library.Events.Messages;
using log4net;
using System.Reflection;
namespace AnguaRPGEngine.Library.Controls
{
    public partial class PartsControl : UserControl
    {
        private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private int _HoverPiece = 0;
        private int _MaxPartsOnPage = 5;
        private int _PartStartIndex = 0;
        private int _SelectedPartIndex = -1;
        private int _SelectedPartType = -1;
        private List<IPart> _Parts = new List<IPart>();
        public PartsControl()
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.Opaque, true);
                InitializeComponent();
                _Parts = new List<IPart>();
                List<Door> doors = Serializer<List<Door>>.DeserializeFromFile(GameSystem.Instance.PathToData + "Images\\Parts\\Door\\Doors.dat");
                List<Floor> floors = Serializer<List<Floor>>.DeserializeFromFile(GameSystem.Instance.PathToData + "Images\\Parts\\Floor\\Floors.dat");
                List<Scenery> scenery = Serializer<List<Scenery>>.DeserializeFromFile(GameSystem.Instance.PathToData + "Images\\Parts\\Scenery\\Scenery.dat");
                List<Wall> walls = Serializer<List<Wall>>.DeserializeFromFile(GameSystem.Instance.PathToData + "Images\\Parts\\Wall\\Walls.dat");
                List<Effect> effects = Serializer<List<Effect>>.DeserializeFromFile(GameSystem.Instance.PathToData + "Images\\Parts\\Effect\\Effects.dat");
                List<Markup> markups = Serializer<List<Markup>>.DeserializeFromFile(GameSystem.Instance.PathToData + "Images\\Parts\\Markup\\Markups.dat");
                if (doors != null)
                {
                    foreach (Door door in doors)
                    {
                        _Parts.Add(door);
                    }
                }
                if (floors != null)
                {
                    foreach (Floor floor in floors)
                    {
                        _Parts.Add(floor);
                    }
                }
                if (scenery != null)
                {
                    foreach (Scenery sc in scenery)
                    {
                        _Parts.Add(sc);
                    }
                }
                if (walls != null)
                {
                    foreach (Wall wa in walls)
                    {
                        _Parts.Add(wa);
                    }
                }
                if (effects != null)
                {
                    foreach (Effect ef in effects)
                    {
                        _Parts.Add(ef);
                    }
                }
                if (markups != null)
                {
                    foreach (Markup mu in markups)
                    {
                        _Parts.Add(mu);
                    }
                }
                cboPartType.SelectedIndex = -1;
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                base.OnPaint(e);
                e.Graphics.Clear(Color.Black);
                Rectangle DrawArea = new Rectangle(pnlLeft.Width, pnlFilter.Height, this.Width - pnlLeft.Width - pnlRight.Width - 1, this.Height - pnlFilter.Height - 1);
                e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.DarkGray), 1f), DrawArea);
                List<IPart> parts = SelectPartsBasedOnTypeAndFilter();
                _MaxPartsOnPage = DrawArea.Width / 100;
                int startIndex = 0;
                int currPart = 0;
                int partX = DrawArea.Left;
                foreach (IPart part in parts)
                {
                    if (startIndex >= _PartStartIndex)
                    {
                        Bitmap bitmap = ImageLibrary.Instance.GetImageFromLibrary(part.ImageName);
                        if (bitmap.Size.Width > 100 || bitmap.Size.Height > 100)
                        {
                            e.Graphics.DrawImage(bitmap, new Rectangle(partX, DrawArea.Top, 100, 100), new Rectangle(0, 0, bitmap.Width, bitmap.Height), GraphicsUnit.Pixel);
                        }
                        else
                        {
                            e.Graphics.DrawImage(bitmap, new Point((partX + 50) - (bitmap.Width / 2), (DrawArea.Top + 50) - (bitmap.Height / 2)));
                        }
                        e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.DarkGreen), 1f), new Rectangle(partX, DrawArea.Top, 100, 100));

                        if (_HoverPiece == currPart)
                        {
                            e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Blue), 1f), new Rectangle(partX + 1, DrawArea.Top + 1, 98, 98));
                        }

                        if (_Parts.IndexOf(part) == _SelectedPartIndex)
                        {
                            e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Lime), 1f), new Rectangle(partX + 2, DrawArea.Top + 2, 96, 96));
                        }
                        partX += 100;
                        currPart++;
                    }
                    if (currPart >= _MaxPartsOnPage)
                    {
                        break;
                    }
                    startIndex++;
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }

        private void cboPartType_SelectedIndexChanged(object sender, EventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                _SelectedPartType = cboPartType.SelectedIndex + 1;
                SelectedPartTypeChangeEvent sptce = new SelectedPartTypeChangeEvent((PartTypes)_SelectedPartType);
                ApplicationController.EventAggregator.SendMessage(sptce);
                _PartStartIndex = 0;
                this.Invalidate();
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }


        private void btnPreviousPart_Click(object sender, EventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                if (_PartStartIndex - 1 < 0)
                {
                    _PartStartIndex = 0;
                }
                else
                {
                    _PartStartIndex--;
                }
                this.Invalidate();
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }

        private void btnPreviousPage_Click(object sender, EventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                if (_PartStartIndex - _MaxPartsOnPage < 0)
                {
                    _PartStartIndex = 0;
                }
                else
                {
                    _PartStartIndex -= _MaxPartsOnPage;
                }

                this.Invalidate();
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }

        private void btnNextPart_Click(object sender, EventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                List<IPart> parts = SelectPartsBasedOnTypeAndFilter();
                if (_PartStartIndex + 1 > parts.Count - 1)
                {
                    _PartStartIndex = parts.Count - 1;
                }
                else
                {
                    _PartStartIndex++;
                }
                this.Invalidate();
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }

        private void btnNextPage_Click(object sender, EventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                List<IPart> parts = SelectPartsBasedOnTypeAndFilter();
                if (_PartStartIndex + _MaxPartsOnPage > parts.Count - 1)
                {
                    _PartStartIndex = parts.Count - 1;
                }
                else
                {
                    _PartStartIndex += _MaxPartsOnPage;
                }

                this.Invalidate();
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }

        private void txtFilter_TextChanged(object sender, EventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                this.Invalidate();
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }

        private void PartsControl_MouseMove(object sender, MouseEventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);

                int newHoverPiece = (e.X - pnlLeft.Width) / 100;
                if (newHoverPiece != _HoverPiece)
                {
                    _HoverPiece = newHoverPiece;
                    this.Invalidate();
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }

        private void PartsControl_MouseClick(object sender, MouseEventArgs e)
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                int index = _PartStartIndex + _HoverPiece;
                List<IPart> parts = SelectPartsBasedOnTypeAndFilter();
                int newSelectedPartIndex = _Parts.IndexOf(parts[index]);
                if (newSelectedPartIndex != _SelectedPartIndex)
                {
                    _SelectedPartIndex = newSelectedPartIndex;
                    SelectedPartChangeEvent spce = new SelectedPartChangeEvent(_Parts[_SelectedPartIndex]);
                    ApplicationController.EventAggregator.SendMessage(spce);
                    this.Invalidate();
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
        }
        public void ClearSelection()
        {
            _SelectedPartIndex = -1;
            SelectedPartChangeEvent spce = new SelectedPartChangeEvent(null);
            ApplicationController.EventAggregator.SendMessage(spce);
            this.Invalidate();
        }
        private List<IPart> SelectPartsBasedOnTypeAndFilter()
        {
            string MethodName = MethodBase.GetCurrentMethod().Name;
            List<IPart> parts = new List<IPart>();
            try
            {
                _Log.DebugFormat("{0} - Entry", MethodName);
                if (txtFilter.Text.Length > 0)
                {
                    parts = _Parts.FindAll(p => p.PartType == (PartTypes)_SelectedPartType && p.Keywords.ToLower().Contains(txtFilter.Text.ToLower()));
                }
                else
                {
                    parts = _Parts.FindAll(p => p.PartType == (PartTypes)_SelectedPartType);
                }
            }
            catch (Exception err)
            {
                _Log.Error(MethodName, err);
            }
            finally
            {
                _Log.DebugFormat("{0} - Exit", MethodName);
            }
            return parts;
        }
    }
}